# -*- coding: utf-8 -*-
# @Author: bao
# @Date:   2017-02-17 11:20:24
# @Last Modified by:   bao
# @Last Modified time: 2017-02-20 22:23:31

import munkres
import networkx as nx

def get_degree_key(item):
	return item[1]['degree']
	
def get_weight(weight):
	integral = int(weight)
	fractional = weight - integral
	if not integral:
		return 1
	else:
		if fractional < 0.5:
			return integral
		else:
			return integral+1

def get_cd(location, row_size):
	'''
	calculate the coordinate
	'''
	axis_x = location%row_size
	if axis_x == 0:
		axis_x = row_size
		axis_y = location/row_size
	else:
		axis_y = location/row_size + 1
	return axis_x, axis_y

def get_cp(cd_src, cd_dst, row_size, base_len):
	'''
	get the cp of src and dst
	'''
	if cd_src[0]==cd_dst[0] or cd_src[1]==cd_dst[1]:
		Is_same_axis = True
		cp_x = 0
		cp_y = 0
	else:
		Is_same_axis = False
		cp_x = cd_dst[0] + (cd_src[1]-1)*row_size + base_len
		cp_y = cd_src[0] + (cd_dst[1]-1)*row_size + base_len

	return Is_same_axis, cp_x, cp_y

class gen_topo(object):
	'''
	Calculate new topolgoy
	Wavelegnth assignment and adjustment
	Four steps:
	1) Generate new topology by transforming the traffic matrix into wavelengh matrix by max_weight_matches
	2) Decomposing the graph to matches based on pre_matches (minimal wavelength adjustment)
	3) Assigning colors to maxmize the overlap
	'''
	def __init__(self):
		self.pre_matches = {} # {port:[(src1,dst1), (src2,dst2)]}

	def _transform(self, wl_graph, tf_graph, degree, base_len):
		'''
		Generate the new topology based on traffic demand matrix (tf_graph)
		Max weight matches
		'''

	def _matchings(self, graph, pre_matches, max_degree, base_len):
		'''
		Minimal Wavelength Adjustment (MWA) based on pre_matches
		Extending the algorithms from paper "WaveCube: A scalable, fault-tolerant, high-performance optical data center architecture"
		'''
		
	def _color_assignment(self, pre_matches, cur_matches, base_len):
		'''
		Baed on the Hungarian to minimize the wavelength adjustment
		Retrun dynamic match, static match and new match
		'''
		s_matches = {} # {port:[(src1,dst1), (src2,dst2)]}
		d_matches = {} # {port:[(src1,dst1), (src2,dst2)]}
		new_matches = {} # {port:[(src1,dst1), (src2,dst2)]}
		cost_matrix = []
		# (i,j) means the same edges of pre_matches[i] and cur_matches[j]
		for i in xrange(0,len(pre_matches)):
			cost_matrix.append(i)
			cost_matrix[i] = []
			for j in xrange(0,len(cur_matches)):
				cost_matrix[i].append(base_len - len(set(pre_matches[i+1]) & set(cur_matches[j+1])))

		# Calculating the minimize wavelength adjustment
		m = munkres.Munkres()
		indexes = m.compute(cost_matrix)
		# Assign colors to get new matches
		index = 0
		for i in pre_matches:
			if index < len(indexes):
				if i == indexes[index][0]+1:
					new_matches[i] = cur_matches[indexes[index][1]+1][:]
					d_matches[i] = list(set(cur_matches[indexes[index][1]+1]) - set(pre_matches[i]))
					s_matches[i] = list(set(cur_matches[indexes[index][1]+1]) & set(pre_matches[i]))
					index +=1
				else:
					s_matches[i] = pre_matches[i]
					new_matches[i] = pre_matches[i]
			else:
				s_matches[i] = pre_matches[i]
				new_matches[i] = pre_matches[i]
		return d_matches, s_matches, new_matches